package com.cfh.springcloudclientapplication.controller;


import com.cfh.springcloudclientapplication.annotation.CustomLoadBalanced;
import com.cfh.springcloudclientapplication.loadbalance.LoadBalancedClientHttpRequestInterceptor;
import com.cfh.springcloudclientapplication.service.SayingRestService;
import com.cfh.springcloudclientapplication.service.SayingService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import java.util.*;
import java.util.stream.Collectors;

@RestController
public class ClientController {

    @Bean
    public ClientHttpRequestInterceptor interceptor() {
        return new LoadBalancedClientHttpRequestInterceptor();
    }


    /**
     * Ribbon RestTemplate Bean
     *
     * @return
     */
    @Bean
    @LoadBalanced
    public RestTemplate loadBalancedRestTemplate() {
        return new RestTemplate();
    }

    /**
     * 自定义 RestTemplate Bean
     */
    @Bean
    @CustomLoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }


    @Bean
    @Autowired
    public Object customizer(@CustomLoadBalanced Collection<RestTemplate> restTemplates,
                             ClientHttpRequestInterceptor interceptor) {
        restTemplates.forEach(
                s ->
                        s.setInterceptors(Arrays.asList(interceptor)));
        return new Object();
    }


    @Autowired
    private RestTemplate restTemplate;


    @Autowired
    @LoadBalanced
    private RestTemplate lbRestTemplate;


    @Autowired
    private SayingService sayingService;

    @Autowired
    private SayingRestService sayingRestService;

    @GetMapping("/invoke/{serviceName}/say")
    public String invokeSay(@PathVariable String serviceName, @RequestParam String message) {
        //RestTemplate 发送请求
        return restTemplate.getForObject(serviceName + "/say?message=" + message, String.class);
    }


    @GetMapping("/lb/invoke/{serviceName}/say")
    public String loadbalanceInvokeSay(@PathVariable String serviceName,
                                       @RequestParam String message) {
        //RestTemplate 发送请求
            return lbRestTemplate.getForObject("http://" + serviceName + "/say?message=" + message,
                    String.class);
    }

    @GetMapping("/feign/say")
    public String feignSay(@RequestParam String message) {
        return sayingService.say(message);
    }

    @GetMapping("/rest/say")
    public String restSay(@RequestParam String message) {
        return sayingRestService.say(message);
    }


//    @Autowired
//    private DiscoveryClient discoveryClient;


    //    @Value("${spring.application.name}")
//    private String serviceName;
//
//    private volatile Set<String> targetUrls = new HashSet<>();
//
//
//    @Scheduled(fixedRate = 10 * 1000)
//    public void updateServiceNames() {
//        List<ServiceInstance> instances = discoveryClient.getInstances(serviceName);
//
//        Set<String> oldTargetUrls = this.targetUrls;
//        Set<String> newTargetUrls = instances
//                .stream()
//                .map(s ->
//                        s.isSecure() ?
//                                "https://" + s.getHost() + ":" + s.getPort() :
//                                "http://" + s.getHost() + ":" + s.getPort()
//                )
//                .collect(Collectors.toSet());
//
//        this.targetUrls = newTargetUrls;
//        oldTargetUrls.clear();
//    }
//
//    @GetMapping("/invoke/say")
//    public String invokeSay(@RequestParam String message) {
//        //服务器列表
//        List<String> targetUrls = new ArrayList<>(this.targetUrls);
//        //选择
//        int index = new Random().nextInt(targetUrls.size());
//        String url = targetUrls.get(index);
//        //RestTemplate 发送请求
//        return restTemplate.getForObject(url + "/say?message=" + message, String.class);
//    }

//    private volatile Map<String, Set<String>> targetUrlsCache = new HashMap<>();


//    @Scheduled(fixedRate = 10 * 1000)
//    public void updateServiceNames() {
//        Map<String, Set<String>> newTargetUrlsCache = this.targetUrlsCache;
//        discoveryClient.getServices().forEach(serviceName -> {
//            List<ServiceInstance> instances = discoveryClient.getInstances(serviceName);
//            Set<String> newTargetUrls = instances
//                    .stream()
//                    .map(s ->
//                            s.isSecure() ?
//                                    "https://" + s.getHost() + ":" + s.getPort() :
//                                    "http://" + s.getHost() + ":" + s.getPort()
//                    )
//                    .collect(Collectors.toSet());
//            newTargetUrlsCache.put(serviceName, newTargetUrls);
//        });
//        this.targetUrlsCache = newTargetUrlsCache;
//    }
}

